package com.cjh.mybatis10.bulider;

import com.cjh.mybatis10.mapping.ParameterMapping;
import com.cjh.mybatis10.mapping.SqlSource;
import com.cjh.mybatis10.parsing.GenericTokenParser;
import com.cjh.mybatis10.parsing.TokenHandler;
import com.cjh.mybatis10.reflection.MetaClass;
import com.cjh.mybatis10.reflection.MetaObject;
import com.cjh.mybatis10.session.Configuration;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Descripton SQL 源码构建器
 * @Author cjh
 * @Date 2023/6/12 14:40
 */
@Slf4j
public class SqlSourceBuilder extends BaseBuilder {
    private static final String parameterProperties = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName";

    public SqlSourceBuilder(Configuration configuration) {
        super(configuration);
    }

    public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameter) {
        ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler
                (configuration, parameterType, additionalParameter);
        GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
        String sql = parser.parse(originalSql);
    //    返回静态sql
        return new StaticSqlSource(sql,handler.getParameterMappings(),configuration);

    }

    private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {
        @Getter
        private List<ParameterMapping> parameterMappings = new ArrayList<>();
        private Class<?> parameterType;
        private MetaObject metaParameter;


        public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType, Map<String, Object> additionalParameters) {
            super(configuration);
            this.parameterType = parameterType;
            this.metaParameter = configuration.newMetaObject(additionalParameters);

        }

        @Override
        public String handleToken(String content) {
            parameterMappings.add(buildParameterMapping(content));
            return "?";
        }

        /**
         * 构建参数映射
         *
         * @param content
         * @return
         */
        private ParameterMapping buildParameterMapping(String content) {
            // 先解析参数映射,就是转化成一个 HashMap | #{favouriteSection,jdbcType=VARCHAR}
            Map<String, String> propertiesMap = new ParameterExpression(content);
            String property = propertiesMap.get("property");

            Class<?> propertyType ;
            if (typeHandlerRegistry.hasTypeHandler(parameterType)){
                propertyType = parameterType;
            }else if (property != null){
                MetaClass metaClass = MetaClass.forClass(parameterType);
                if (metaClass.hasGetter(property)){
                    propertyType = metaClass.getGetterType(property);
                }else {
                    propertyType = Object.class;
                }
            }else {
                propertyType = Object.class;
            }
            log.info("构建参数映射 property：{} propertyType：{}", property, propertyType);

            ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
            return builder.build();


        }
    }


}
